package com.lujieni.threadpool.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.lujieni.threadpool.dao.ThreadPoolTaskDao;
import com.lujieni.threadpool.decorate.CustomTaskDecorator;
import com.lujieni.threadpool.po.ThreadPoolTaskPO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.Date;
import java.util.concurrent.*;

/**
 * @author lujieni
 * @date 2022/9/20 13:05
 * @description 配置线程池
 */
@Configuration
public class ThreadPoolConfig {

    @Autowired
    private DatabaseRejectedExecutionHandler databaseRejectedExecutionHandler;

    @Autowired
    private ThreadPoolTaskDao threadPoolTaskDao;

    @Bean("sayContentThreadPool")
    public ExecutorService sayContentThreadPool(){
        ThreadFactory threadFactory = new CustomizableThreadFactory("say-content-thread-pool");

        return new ThreadPoolExecutor(1, 1,
                10L, TimeUnit.SECONDS,
                new LinkedBlockingQueue(1),
                threadFactory,
                databaseRejectedExecutionHandler) {

            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                String taskInfo = r.toString();
                ThreadPoolTaskPO taskPO = JSON.parseObject(taskInfo, ThreadPoolTaskPO.class);
                if (taskPO.getId() != null) {
                    ThreadPoolTaskPO record = new ThreadPoolTaskPO();
                    record.setId(taskPO.getId());
                    record.setActive(0);
                    record.setModifyTime(new Date());
                    threadPoolTaskDao.updateByPrimaryKeySelective(record);
                }
            }
        };
    }

    /**
     * 下面的配置是配置Springboot的@Async注解所用的线程池
     */
    @Bean
    public ThreadPoolTaskExecutor lujieniAsyncPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置线程池核心容量
        executor.setCorePoolSize(20);
        // 设置线程池最大容量
        executor.setMaxPoolSize(20);
        // 设置任务队列长度
        executor.setQueueCapacity(20);
        // 设置线程超时时间
        executor.setKeepAliveSeconds(60);
        // 设置线程名称前缀
        executor.setThreadNamePrefix("lujieniAsyncPool-");
        // 存入数据库
        executor.setRejectedExecutionHandler(databaseRejectedExecutionHandler);
        executor.setTaskDecorator(new CustomTaskDecorator());
        executor.initialize();
        return executor;
    }

    @Bean
    public ThreadPoolTaskExecutor fuckAsyncPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置线程池核心容量
        executor.setCorePoolSize(25);
        // 设置线程池最大容量
        executor.setMaxPoolSize(25);
        // 设置任务队列长度
        executor.setQueueCapacity(100);
        // 设置线程超时时间
        executor.setKeepAliveSeconds(60);
        // 设置线程名称前缀
        executor.setThreadNamePrefix("fuckAsyncPool-");
        // 设置任务丢弃后的处理策略,当poolSize已达到maxPoolSize，如何处理新任务（是拒绝还是交由其它线程处理）,CallerRunsPolicy：不在新线程中执行任务，而是由调用者所在的线程来执
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        executor.setWaitForTasksToCompleteOnShutdown(true); //使用shutdown
        executor.setAwaitTerminationSeconds(30); // shutdown之后强制主线程等待30秒,30秒还没执行完就打断线程池中的线程
        //executor.setTaskDecorator(new CustomTaskDecorator());
        executor.initialize();
        return executor;
    }

    /**
     * 为了专门测试装配器的线程池
     * @return
     */
    @Bean
    public ThreadPoolTaskExecutor taskDecoratorAsyncPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置线程池核心容量
        executor.setCorePoolSize(1);
        // 设置线程池最大容量
        executor.setMaxPoolSize(1);
        // 设置任务队列长度
        executor.setQueueCapacity(2000);
        // 设置线程超时时间
        executor.setKeepAliveSeconds(60);
        // 设置线程名称前缀
        executor.setThreadNamePrefix("taskDecoratorAsyncPool-");
        // 存入数据库
        executor.setRejectedExecutionHandler(databaseRejectedExecutionHandler);
        executor.setTaskDecorator(new CustomTaskDecorator());
        executor.initialize();
        return executor;
    }

    /**
     * 普通线程池
     * @return
     */
    @Bean
    public ThreadPoolTaskExecutor commonThreadPool() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置线程池核心容量
        executor.setCorePoolSize(1);
        // 设置线程池最大容量
        executor.setMaxPoolSize(3);
        // 设置任务队列长度
        executor.setQueueCapacity(7);
        // 设置线程超时时间
        executor.setKeepAliveSeconds(60);
        // 设置线程名称前缀
        executor.setThreadNamePrefix("commonThreadPool-");
        executor.initialize();
        return executor;
    }


    @Bean("ttlExecutorService")
    public ExecutorService ttlExecutorService(){
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1,
                1000L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(300),
                new CustomizableThreadFactory("ttl-thread-pool"),
                databaseRejectedExecutionHandler) {
        };
        return TtlExecutors.getTtlExecutorService(threadPoolExecutor);
    }
}
